Repository navigation
Freeze released isolated sessions and project markers (#271) - #291
Merged
Merged
Conversation
The Sessions and project family of the persisted-contracts D rows. tests/fixtures/persisted/sessions/<release>/ holds what v0.1.2, v0.2.0 and v0.3.0 wrote with their own CLIs. freeze.py runs the release's `syncmill init` (the marker stays untracked and ignored, syncmill.toml is committed), then `session open codex --no-attach` against a fake interactive codex in a real tmux. A tmux on the fake PATH execs the real one with a private socket and no config, so the user's server is never touched. - project: syncmill.toml and the marker directory's project.json and .gitignore, stored as marker.json and marker.gitignore: from v0.2.0 init's .gitignore names project.json, so Git would ignore the marker under its own name. Its 0600 mode is asserted and recorded. - open, checkpointed (one checkpoint run artifact), closed; - creating, closing, recovery-required: an exit on entry to the tmux launch, an exit right after the closing document, and a cleanup that reports failure, from a .pth hook loaded for the run only. Workspaces are not frozen: they are Git repositories holding absolute paths. The test rebinds each session document's four paths and fingerprint and the checkpoint manifest's root and fingerprint, with exact counts, and asserts every other field unchanged; the tmux name re-derives. tmux is never launched: the store's probe, commands and attachment and the CLI's gates are patched. It reads: - session isolated-list (live from the probe, staleness in the stored fingerprint's version, open sessions only), render_session; - load's path binding: a document under another workspace root, with another tmux name, a worktree outside its run root or another repository is skipped by list and refused by checkpoint; - attach-isolated (not running, a pane elsewhere, the one right pane), refused from every non-open state; checkpoint without its worktree; close of every state with the workspace gone (each ends closed at a pinned revision; a closed one is returned unchanged); - the checkpoint artifact through runs list/show, diff, conversations show/list/close, continue (refused: no provider session), recover (skipped), apply, validate_applicable, discard and prune (pending kept, removed once discarded), and the TUI's render_artifact and _read_artifact_result; - project_id with the released marker untracked (its id), tracked or symlinked (the path hash), load_project_config of the released config, and initialize_project falling back to the marker. 14 injected regressions in isolated_session.py, project.py and artifacts.py each fail an intended assertion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 1: - the installed fingerprint is now asserted to keep the released v1 version (a recompute that ignored like= upgraded it to v2 before any reader saw it, and every test still passed); - applying the released checkpoint must leave the artifact applied with its receipt bound to the apply (skipping the applied flip passed); - release discovery takes only v*/ directories holding bindings.json (importing freeze.py made __pycache__ a "release"); - freeze.py stops its private tmux server before the box is removed and proves it gone; if it cannot, the socket is kept and its kill command printed. Generation output is unchanged. 16 injected regressions now each fail an intended assertion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 2: - freeze.py now removes neither the box nor the socket, and exits nonzero, when it cannot prove its private tmux server stopped (round 1's fix still deleted the box and returned success); checked with the shutdown reported as failed; - the released config is also checked for its config_version and project.memory_dir; - conversations close is checked against a pinned clock instead of a timestamp that merely differs. 16 injected regressions still each fail an intended assertion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #271. This is the Sessions and project family. It follows the convention of the artifacts, rooms and workflows families. The issue stays open.
What
tests/fixtures/persisted/sessions/freeze.pywrites the fixtures for v0.1.2, v0.2.0 and v0.3.0, each with the release's own CLI.syncmill init. The marker stays untracked and ignored, andsyncmill.tomlis committed.session open codex --no-attachagainst a fake interactive codex in a real tmux.tmuxon the fake PATH execs the real binary with a private socket and no config, so the user's server is never touched.project:syncmill.tomlplus the marker directory'sproject.jsonand.gitignore, stored asmarker.jsonandmarker.gitignore. From v0.2.0,init's.gitignorenamesproject.jsonitself, so Git would ignore the marker under its own name. Its 0600 mode is asserted and recorded.open;checkpointed, with one checkpoint run artifact;closed.creating,closing,recovery-required, from a.pthhook loaded for the run only: an exit on entry to the tmux launch, an exit right after theclosingdocument, and a cleanup that reports failure.session isolated-list(liveness from the probe, staleness in the stored version, open sessions only) andrender_session.listand refused bycheckpoint.attach-isolated: refused when the session is not running or a pane is elsewhere, attached to the one right pane, and refused from every non-open state.checkpointwithout its worktree.closeof every state with the workspace gone: each endsclosedat a pinned revision, and a closed one is returned unchanged.runs list/show,diff, andconversations show/list/close;continuerefused (no provider session), andrecoverskipped;apply(left applied with its receipt bound) andvalidate_applicable;discard, andprune, which keeps it while pending and removes it once discarded;render_artifactand_read_artifact_result.project_idwith the released marker untracked (its id), and tracked or symlinked (the path hash);load_project_configof the released config, value for value;initialize_projectfalling back to the marker.docs/architecture/persisted-contracts.md: the row names these. Not covered: a successful checkpoint or worktree cleanup, because a release-written workspace is not relocatable.No source under
src/changes. No current reader misread a released session or marker.Verification
suite-runCLEAN;ruff check .clean.isolated_session.py,project.py,artifacts.pyandworktree.pyeach fail an intended assertion. They include:56535a0.__pycache__.1eacaf9.🤖 Generated with Claude Code